/*
 * Code for blog.techhead.biz
 * Distributed under BSD-style license
 */

package biz.techhead.funcy;

/**
 * For the definition of a Tuple, see the {@link Tuple Tuple} class.
 * 
 * <p>This class simply provides the means to create a Tuple of any size
 * zero through nine.
 *
 * @author Jonathan Hawkes <jhawkes at techhead.biz>
 */
public class Tuples {

    public static final T0 T0 = new T0();

    public static T0 T() { return T0; }
    public static <A> T1<A> T(A a) { return new T1<A>(a); }
    public static <A,B> T2<A,B> T(A a, B b) { return new T2<A,B>(a,b); }

    public static <A,B,C> T3<A,B,C> T(A a, B b, C c) {
        return new T3<A,B,C>(a,b,c);
    }

    public static <A,B,C,D> T4<A,B,C,D> T(A a, B b, C c, D d) {
        return new T4<A,B,C,D>(a,b,c,d);
    }

    public static <A,B,C,D,E> T5<A,B,C,D,E> T(A a, B b, C c, D d, E e) {
        return new T5<A,B,C,D,E>(a,b,c,d,e);
    }

    public static <A,B,C,D,E,F> T6<A,B,C,D,E,F>
            T(A a, B b, C c, D d, E e, F f) {
        return new T6<A,B,C,D,E,F>(a,b,c,d,e,f);
    }

    public static <A,B,C,D,E,F,G> T7<A,B,C,D,E,F,G>
            T(A a, B b, C c, D d, E e, F f, G g) {
        return new T7<A,B,C,D,E,F,G>(a,b,c,d,e,f,g);
    }

    public static <A,B,C,D,E,F,G,H> T8<A,B,C,D,E,F,G,H>
            T(A a, B b, C c, D d, E e, F f, G g, H h) {
        return new T8<A,B,C,D,E,F,G,H>(a,b,c,d,e,f,g,h);
    }

    public static <A,B,C,D,E,F,G,H,I> T9<A,B,C,D,E,F,G,H,I>
            T(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
        return new T9<A,B,C,D,E,F,G,H,I>(a,b,c,d,e,f,g,h,i);
    }

    public static class T0 extends Tuple {
        T0(int length, int hashCode) {
            super(length, hashCode);
        }
        public T0() {
            this(0, 0);
        }    
    }

    public static class T1<A> extends T0 {

        public final A _1;

        T1(int length, int hashCode, A a) {
            super(length, hashCode(hashCode,a));
            _1 = a;
        }

        public T1(A a) {
            this(1, 1, a);
        }
    }

    public static class T2<A,B> extends T1<A> {

        public final B _2;

        T2(int length, int hashCode, A a, B b) {
            super(length, hashCode(hashCode,b), a);
            _2 = b;
        }

        public T2(A a, B b) {
            this(2, 1, a, b);
        }
    }

    public static class T3<A,B,C> extends T2<A,B> {

        public final C _3;

        T3(int length, int hashCode, A a, B b, C c) {
            super(length, hashCode(hashCode,c), a, b);
            _3 = c;
        }

        public T3(A a, B b, C c) {
            this(3, 1, a, b, c);
        }
    }

    public static class T4<A,B,C,D> extends T3<A,B,C> {

        public final D _4;

        T4(int length, int hashCode, A a, B b, C c, D d) {
            super(length, hashCode(hashCode,d), a, b, c);
            _4 = d;
        }

        public T4(A a, B b, C c, D d) {
            this(4, 1, a, b, c, d);
        }
    }

    public static class T5<A,B,C,D,E> extends T4<A,B,C,D> {

        public final E _5;

        T5(int length, int hashCode, A a, B b, C c, D d, E e) {
            super(length, hashCode(hashCode,e), a, b, c, d);
            _5 = e;
        }

        public T5(A a, B b, C c, D d, E e) {
            this(5, 1, a, b, c, d, e);
        }
    }

    public static class T6<A,B,C,D,E,F> extends T5<A,B,C,D,E> {

        public final F _6;

        T6(int length, int hashCode, A a, B b, C c, D d, E e, F f) {
            super(length, hashCode(hashCode,f), a, b, c, d, e);
            _6 = f;
        }

        public T6(A a, B b, C c, D d, E e, F f) {
            this(6, 1, a, b, c, d, e, f);
        }
    }

    public static class T7<A,B,C,D,E,F,G> extends T6<A,B,C,D,E,F> {

        public final G _7;

        T7(int length, int hashCode, A a, B b, C c, D d, E e, F f, G g) {
            super(length, hashCode(hashCode,g), a, b, c, d, e, f);
            _7 = g;
        }

        public T7(A a, B b, C c, D d, E e, F f, G g) {
            this(7, 1, a, b, c, d, e, f, g);
        }
    }

    public static class T8<A,B,C,D,E,F,G,H> extends T7<A,B,C,D,E,F,G> {

        public final H _8;

        T8(int length, int hashCode, A a, B b, C c, D d, E e, F f, G g, H h) {
            super(length, hashCode(hashCode,h), a, b, c, d, e, f, g);
            _8 = h;
        }

        public T8(A a, B b, C c, D d, E e, F f, G g, H h) {
            this(8, 1, a, b, c, d, e, f, g, h);
        }
    }

    public static class T9<A,B,C,D,E,F,G,H,I> extends T8<A,B,C,D,E,F,G,H> {

        public final I _9;

        protected T9(int length, int hashCode, A a, B b, C c, D d, E e, F f,
                G g, H h, I i) {
            super(length, hashCode(hashCode,i), a, b, c, d, e, f, g, h);
            _9 = i;
        }

        public T9(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
            this(9, 1, a, b, c, d, e, f, g, h, i);
        }
    }
}
